#pragma once
#include <iostream>
#include <memory>
#include <unordered_map>
#include "Epoller.hpp"
#include "Connection.hpp"

class Reactor
{
    const static int _revs_num = 64;
public:
    Reactor():_ep_server(std::make_unique<Epoller>()),_is_running(false)
    {
    }
    void Init()
    {
        _ep_server->Init();
    }
    void InsertConnection(connection_t conn)
    {
        auto it = _conns.find(conn->Sockfd());
        if(it==_conns.end())
        {
            _conns.insert(std::make_pair(conn->Sockfd(),conn));
            _ep_server->Add(conn->Sockfd(),conn->GetEvents());
            //设置关联关系
            conn->SetOwner(this);

        }
        else
        {
            std::cout<<"添加listen连接失败"<<std::endl;
        }
    }

    void Dispatcher(int n)
    {
        for(int i = 0;i<n;i++)
        {
            int sockfd = _revs[i].data.fd;
            uint32_t revents = _revs[i].events;
            //将错误类型全转为EPOLLIN和EPOLLOUT来处理
            if((revents&EPOLLERR)||(revents&EPOLLHUP))
            {
                revents = (EPOLLIN|EPOLLOUT);
            }
            if((revents&EPOLLIN)&&IsConnExits(sockfd))
            {
                _conns[sockfd]->Recv();
            }
            if((revents&EPOLLOUT)&&IsConnExits(sockfd))
            {
                _conns[sockfd]->Send();
            }            

        }
    }
    void LoopOnce()
    {
        int n = _ep_server->Wait(_revs,_revs_num);
        Dispatcher(n);
    }
    void Loop()
    {

        _is_running = true;
        while(_is_running)
        {
            LoopOnce();
        }
        _is_running = false;

    }

    void EnableReadWrite(int sockfd,bool readable,bool writeable)
    {
        if(IsConnExits(sockfd))
        {
            //重置
            uint32_t events = ((readable?EPOLLIN:0)|(writeable?EPOLLIN:0)|EPOLLET);
            _ep_server->Mod(sockfd,events);
        }
    }
    void DelConnection(int sockfd)
    {
        //1.将文件描述符从内核中移除
        _ep_server->Del(sockfd);
        //用户层移除连接
        if(IsConnExits(sockfd))
        {
            _conns.erase(sockfd);
        }
        //关闭文件描述符
        close(sockfd);
    }
    ~Reactor()
    {

    }
private:
    bool IsConnExits(int sockfd)
    {
        return _conns.find(sockfd)!=_conns.end();
    }
private:
    std::unique_ptr<Epoller> _ep_server;
    std::unordered_map<int,connection_t> _conns;
    struct epoll_event _revs[_revs_num];
    bool _is_running;
};